package com.yxw.live_vod_boot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxw.live_vod_boot.dto.VideoLikeDTO;
import com.yxw.live_vod_boot.dto.VideoLikeListQueryDTO;
import com.yxw.live_vod_boot.dto.VodLikeAndCollectDto;
import com.yxw.live_vod_boot.entity.YxOnDemandCollectionFolderEntity;
import com.yxw.live_vod_boot.entity.YxOnDemandVideoEntity;
import com.yxw.live_vod_boot.entity.YxVideoLikeEntity;
import com.yxw.live_vod_boot.mapper.OnDemandLikeMapper;
import com.yxw.live_vod_boot.service.OnDemandLikeService;
import com.yxw.live_vod_boot.utils.AssertUtil;
import com.yxw.live_vod_boot.utils.PageUtils;
import com.yxw.live_vod_boot.utils.RedisManager;
import com.yxw.live_vod_boot.vo.OnDemandCollectionFolderVO;
import com.yxw.live_vod_boot.vo.OnDemandVideoVo;
import com.yxw.live_vod_boot.vo.VideoLikeInfoVo;
import com.yxw.live_vod_boot.vo.VodLikeAndCollectVo;
import com.yxw.yxnet_cd_center.common.constant.RedisIdConstant;
import com.yxw.yxnet_cd_center.common.dto.PageVO;
import com.yxw.yxnet_cd_center.common.enums.ErrorCodeEnum;
import com.yxw.yxnet_cd_center.common.utils.BaseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 点播点赞管理
 *
 * @author liuxin
 * @date 2023.11.24
 */
@Service
public class OnDemandLikeServiceImpl extends ServiceImpl<OnDemandLikeMapper, YxVideoLikeEntity> implements OnDemandLikeService {

    @Autowired
    private RedisManager redisManager;

    @Resource
    private RedisTemplate redisTemplate;


    @Autowired
    private OnDemandLikeMapper onDemandLikeMapper;

    /**
     * 视频点赞
     *
     * @param dto
     */
    @Override
    public void doVideoLike(VideoLikeDTO dto) {
        //查询是否存在点赞
        Boolean exist = redisManager.existBySet(RedisIdConstant.ON_DEMAND_VIDEO_LIKE + ":" + dto.getVideoId(), dto.getUserId());
        //查询总点赞数量
        Integer cnt = 0;
        Object obj = redisManager.get(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_CNT + ":" + dto.getVideoId());
        if (null != obj) {
            cnt = (Integer) obj;
        }
        //存在点赞就取消点赞
        if (exist) {
            //取消点赞
            redisManager.delBySet(RedisIdConstant.ON_DEMAND_VIDEO_LIKE + ":" + dto.getVideoId(), dto.getUserId());
            //点赞数-1
            redisManager.set(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_CNT + ":" + dto.getVideoId(), cnt - 1);
            //新增新增取消点赞集合
            redisManager.addBySet(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_DEL + ":" + dto.getVideoId(), dto.getUserId());
            //删除新增点赞集合
            redisManager.delBySet(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_ADD + ":" + dto.getVideoId(), dto.getUserId());
        } else {
            //增加点赞
            redisManager.addBySet(RedisIdConstant.ON_DEMAND_VIDEO_LIKE + ":" + dto.getVideoId(), dto.getUserId());
            //点赞数量加1
            redisManager.set(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_CNT + ":" + dto.getVideoId(), cnt + 1);
            //添加新增点赞集合
            redisManager.addBySet(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_ADD + ":" + dto.getVideoId(), dto.getUserId());
            //删除新增取消点赞集合
            redisManager.delBySet(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_DEL + ":" + dto.getVideoId(), dto.getUserId());
        }
    }

    /**
     * getVideoLikeInfo
     *
     * @param dto
     */
    @Override
    public BaseResult<VideoLikeInfoVo> getVideoLikeInfo(VideoLikeDTO dto) {
        VideoLikeInfoVo vo = new VideoLikeInfoVo();
        //查询是否点赞
        Boolean exist = redisManager.existBySet(RedisIdConstant.ON_DEMAND_VIDEO_LIKE + ":" + dto.getVideoId(), dto.getUserId());
        vo.setIsLike(exist);
        //查询点赞量
        Integer cnt = 0;
        Object obj = redisManager.get(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_CNT + ":" + dto.getVideoId());
        if (null != obj) {
            cnt = (Integer) obj;
        }
        vo.setLikeCnt(cnt);
        return BaseResult.doSuccess(vo, "查询成功");
    }

    /**
     * 点播点赞信息从redis添加到数据库
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addLikeRecord() {
        //查询新增点赞前缀
        Set<String> addKeys = redisTemplate.keys(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_ADD + ":" + "*");
        if (null != addKeys) {
            List<YxVideoLikeEntity> entityList = new ArrayList<>();
            for (String key : addKeys) {
                //根据key的分隔符获取视频ID
                String videoId = key.split(":")[1];
                String addKey = RedisIdConstant.ON_DEMAND_VIDEO_LIKE_ADD + ":" + videoId;
                //查询视频对应的点赞人
                Set<Integer> userIds = redisTemplate.opsForSet().members(addKey);
                for (Integer userId : userIds) {
                    YxVideoLikeEntity entity = new YxVideoLikeEntity();
                    entity.setUserId(Long.valueOf(userId));
                    entity.setVideoId(Long.valueOf(videoId));
                    entity.setLikeTime(new Date());
                    entityList.add(entity);
                }
                //新增完以后及时删除
                redisTemplate.delete(addKey);
            }
            //批量写记录
            if (!entityList.isEmpty()) {
                Integer size = entityList.size();
                Integer pageSize = 1500;
                Integer num = size % pageSize == 0 ? size / pageSize : size / pageSize + 1;
                for (int i = 0; i < num; i++) {
                    onDemandLikeMapper.saveByBatch(entityList.stream().skip(i * pageSize).limit((pageSize)).collect(Collectors.toList()));
                }
            }
            //删除集合
            Set<String> delKeys = redisTemplate.keys(RedisIdConstant.ON_DEMAND_VIDEO_LIKE_DEL + ":" + "*");
            for (String key : delKeys) {
                //根据key的分隔符获取视频ID
                String videoId = key.split(":")[1];
                String delKey = RedisIdConstant.ON_DEMAND_VIDEO_LIKE_DEL + ":" + videoId;
                Set<String> userIds = redisTemplate.opsForSet().members(delKey);
                Integer size = userIds.size();
                //每次最大删除800条
                Integer pageSize = 800;
                Integer num = size % pageSize == 0 ? size / pageSize : size / pageSize + 1;
                for (int i = 0; i < num; i++) {
                    LambdaUpdateWrapper<YxVideoLikeEntity> deleteWrapper = new LambdaUpdateWrapper();
                    deleteWrapper.eq(YxVideoLikeEntity::getVideoId, videoId);
                    deleteWrapper.in(YxVideoLikeEntity::getUserId, userIds.stream().skip(i * pageSize).limit((pageSize)).collect(Collectors.toList()));
                    baseMapper.delete(deleteWrapper);
                }
                redisTemplate.delete(delKey);
            }
        }
    }

    /**
     * 展示当前用户点赞视频列表
     */
    @Override
    public PageVO<OnDemandVideoVo> getVideoLikeListByUserId(VideoLikeListQueryDTO dto) {
        AssertUtil.isNotNull(dto.getUserId(), ErrorCodeEnum.COLLECTION_USER_ID_ERROR);
        Page<YxOnDemandVideoEntity> page = new Page<>(dto.getCurrPage(), dto.getPageSize());
        List<OnDemandVideoVo> list = onDemandLikeMapper.getVideoLikeListByUserId(page, dto.getUserId());
        return PageUtils.get(page, list);
    }

    /**
     * 查询店铺视频点赞和收藏列表
     *
     * @param dto
     * @return
     */
    @Override
    public PageVO<VodLikeAndCollectVo> getVodLikeAndCollectList(VodLikeAndCollectDto dto) {
        //这里从数据取，可能存在时间差
        Page<VodLikeAndCollectVo> page = new Page<>(dto.getCurrPage(), dto.getPageSize());
        List<VodLikeAndCollectVo> voList = onDemandLikeMapper.getVodLikeAndCollectList(page, dto.getShopId());
        return PageUtils.get(page, voList);
    }
}
